package com.erastep.mvc.module
{
	import com.erastep.mvc.EraStepFrame;
	import com.erastep.mvc.ifc.IMedator;
	import com.erastep.mvc.ifc.IModule;
	import com.erastep.mvc.ifc.INotification;
	import com.erastep.mvc.ifc.IProxy;
	import com.erastep.mvc.mediator.Mediator;
	import com.erastep.mvc.observer.Notification;
	import com.erastep.mvc.proxy.Proxy;
	import com.erastep.util.CommonConstants;
	import com.erastep.util.LogUtil;
	import com.erastep.util.StringUtil;
	
	import mx.controls.Alert;

	/**
	 * @author Jarvis
	 * */
	public class SimpleModule  implements IModule
	{ 
		protected var moduleId:String;
		
		public function SimpleModule(moduleId:String = null)
		{
			this.moduleId = moduleId
			mediatorMap = new Array();
			proxyMap = new Array();
		}
		
		public function get mediators():Array{
			return mediatorMap;
		}
		
		public function get proxys():Array{
			return proxyMap;
		}
		
		/**
		 * execute this method first
		 * */
		public function execute(note:INotification):void{
			//at here instance view
		}
		
		/**
		 * execute anather message
		 * */
		public function executeMessage(note:String,body:Object=null,type:String=null,toId:String = null,fromId:String = null):void{
			//at here instance view
			if(toId+"_0" != this.moduleId){
				sendNotification(note,body,type,toId,fromId);
			}else{
				sendNotification(note,body,type,null,fromId);
			}
		}
		
	    public function sendNotification( notificationName:String, body:Object=null, type:String=null ,toId:String = null,fromId:String = null):void{
			//if this moduleId is null
			if(!fromId){
				fromId = this.moduleId;
			}
			if(toId){
				if(toId == this.moduleId){
					//in this module
					methodHandler(notificationName,body,type,toId,fromId);
				}else if(toId == CommonConstants.VICTOPFRAME){
					//send message to frame
					EraStepFrame.getInstance().sendNotification(notificationName,body,type,CommonConstants.VICTOPFRAME,fromId);
				}else{
					//send message to other module
					EraStepFrame.getInstance().sendNotification(notificationName,body,type,toId,fromId);
				}
			}else{
            	//in this module check message。		
				methodHandler(notificationName,body,type,toId,fromId);
			}
		}
		//in all instance find method
		private function methodHandler(note:String,body:Object,type:String,toId:String,fromId:String):void{
			var func:Function;
			var listFun:Array = new Array();
			//check this frame
			var methodName:String = StringUtil.getMethodName(note);
			if(hasOwnProperty(methodName)){
				func = this[methodName] as Function;
				if(func != null){
					listFun.push(func);
				}
			}
			//check all mediator
			for each(var md:Mediator in mediatorMap){
				if(md.hasOwnProperty(methodName)){
					func = md[methodName] as Function;
					if(func != null){
						listFun.push(func);
					}
				}
			}
			//check all proxy
			for each(var py:Proxy in proxyMap){
                if(py.hasOwnProperty(methodName)){
					func = py[methodName] as Function;
					if(func != null){
						listFun.push(func);
					}
				}			
			}
			if(listFun.length > 0){
				for each(func in listFun){
					func.call(null,new Notification(note,body,type,toId,fromId));             //call function
				}
			}else{
				//no method worming
				LogUtil.print("Can not find << "+methodName +" >> Method _Module!");
				Alert.show(CommonConstants.WORMING_MESSAGE+" <<"+methodName+">> Method _Module!",CommonConstants.WORMING_TITLE);
			}
			 
		}
		public static function getInstance() : IModule 
		{
			if (instance == null) instance = new SimpleModule( );
			return instance;
		}
		// Singleton instance
		protected static var instance : IModule;
		
	    /**
		 * @param mediator 
		 * */
		public function registerMediator(mediator:IMedator):void{
			// do not allow re-registration (you must to removeMediator fist)
			if ( mediatorMap[ mediator.getMediatorName() ] != null ) return;
			
			mediator.MessageManager = this;
			
			// Register the Mediator for retrieval by name
			mediatorMap[ mediator.getMediatorName() ] = mediator;
			/*if(mediator.viewComponent){
				if(mediator.viewComponent.hasOwnProperty("callLater")){
					var fun:Function = mediator.viewComponent.callLater as Function;
					fun.call(null,mediator.onRegister());
				}else{
					mediator.onRegister();
				}
			}else{*/
				// alert the mediator that it has been registered
			mediator.host = this._host;
			mediator.onRegister();
			//}
		}
		/**
		 * remove mediator
		 * */
		public function removeMediator(mediatorName:String):void{
			// do not allow re-registration (you must to removeMediator fist)
			if (mediatorMap[mediatorName] == null)
				return;
			
			var _mediator:Mediator = mediatorMap[mediatorName] as Mediator;
			_mediator.onRemove();
			_mediator = null;
			mediatorMap[mediatorName] = null;
			delete mediatorMap[mediatorName];
		}
		
		/**
		 * retrive mediator
		 * */
		public function retriveMediator(mediatorName:String):IMedator{
			if (mediatorMap[mediatorName] == null)
				return null;
			return mediatorMap[mediatorName] as IMedator;
		}
		
		/**
		 * retrive proxy
		 * */
		public function retriveProxy(proxyName:String):IProxy{
			if ( proxyMap[ proxyName ] == null ) return null;
			return proxyMap[ proxyName ] as IProxy;
		}
		
		/**
		 * @param proxy 
		 * */
		public function registerProxy(proxy:IProxy):void{
			// do not allow re-registration (you must to removeMediator fist)
			if ( proxyMap[ proxy.getProxyName() ] != null ) return;
			
			proxy.MessageManager = this;
			
			// Register the Mediator for retrieval by name
			proxyMap[ proxy.getProxyName() ] = proxy;
			proxy.host = _host;
			proxy.onRegister();
			// alert the mediator that it has been registered
		}
		/**
		 * remove proxy
		 * */
		public function removeProxy(proxyName:String):void{
			// do not allow re-registration (you must to removeMediator fist)
			if ( proxyMap[ proxyName ]  == null)
				return;
			
			var _proxy:Proxy = proxyMap[ proxyName ] as Proxy;
			_proxy.onRemove();
			_proxy = null;
			proxyMap[ proxyName ] = null;
			delete proxyMap[ proxyName ];
		}
		
		//get the module key 
		public function get moduleKey():String{
			return moduleId;
		}
		
		// Mapping of Mediator names to Mediator instances
		private var mediatorMap : Array;
		
		
		// Mapping of Mediator names to Mediator instances
		private var proxyMap : Array;
		
		//host url
		private var _host:String;
		
		public function setHostUrl(url:String):void{
			this._host = url;
		}
		/**
		 * start destory
		 * */
		public function onRemove():void{
			mediatorMap = null;
			proxyMap = null;
			_host = null;
		}
	}
}